﻿/*
 * Copyright (c) United Binary LLC.  All rights reserved.
 * 
 * This code is licensed under the MIT License
 * 
 * SEE: http://harnessit.codeplex.com/license
 * 
 */
using System;

namespace UnitedBinary.UnitTests.Framework
{
	public class StringTestExtensionItem : TestExtensionItem, ITestStringsDoes, ITestStringsIs, ITestStringAnd
	{
		private string textUnderTest;
		private ITestStringsDoes myDoes;
		private ITestStringsIs myIs;

		public StringTestExtensionItem(string textUnderTest)
		{
			this.textUnderTest = textUnderTest;
			myDoes = this;
			myIs = this;
		}

		ITestStringsDoes ITestStringsDoes.Contain(string substring)
		{
			return myDoes.Contain( substring, Ignoring.Nothing );
		}

		ITestStringsDoes ITestStringsDoes.Contain(string substring, Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			substring = TransformByIgnores( substring, ignoreFlags );

			TestMethodRecord.Current.RunTest( 
				text.Contains( substring ), 
				"Contains the substring <" + substring + ">" );

			return this;
		}

		private string TransformByIgnores(string text, Ignoring ignoreFlags)
		{
			if ((ignoreFlags | Ignoring.Case) != 0)
			{
				text = text.ToLower();
			}

			if ((ignoreFlags | Ignoring.Whitespace) != 0)
			{
				text = text.Trim();
			}
			else
			{
				if ( (ignoreFlags | Ignoring.LeadingWhitespace) != 0 )
				{
					text = text.TrimStart();
				}

				if ( (ignoreFlags | Ignoring.TrailingWhitespace) != 0 )
				{
					text = text.TrimEnd();
				}
			}

			return text;
		}

		ITestStringsDoes ITestStringsDoes.NotContain(string substring, Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			substring = TransformByIgnores( substring, ignoreFlags );

			TestMethodRecord.Current.RunTest(
				!text.Contains( substring ),
				"Does not contain the substring <" + substring + ">" );

			return this;
		}

		ITestStringsDoes ITestStringsDoes.NotContain(string substring)
		{
			return myDoes.NotContain( substring, Ignoring.Nothing );
		}

		ITestStringsDoes ITestStringsDoes.StartWith(string substring)
		{
			return myDoes.StartWith( substring, Ignoring.Nothing );
		}

		ITestStringsDoes ITestStringsDoes.StartWith(string substring, Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			substring = TransformByIgnores( substring, ignoreFlags );

			TestMethodRecord.Current.RunTest(
				text.StartsWith( substring ),
				"Starts with the substring <" + substring + ">" );

			return this;
		}

		ITestStringsDoes ITestStringsDoes.NotStartWith(string substring)
		{
			return myDoes.NotStartWith( substring, Ignoring.Nothing );
		}

		ITestStringsDoes ITestStringsDoes.NotStartWith(string substring, Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			substring = TransformByIgnores( substring, ignoreFlags );

			TestMethodRecord.Current.RunTest(
				!text.StartsWith( substring ),
				"Does not start with the substring <" + substring + ">" );

			return this;
		}

		ITestStringsDoes ITestStringsDoes.EndsWith(string substring)
		{
			return myDoes.EndsWith( substring, Ignoring.Nothing );
		}

		ITestStringsDoes ITestStringsDoes.EndsWith(string substring, Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			substring = TransformByIgnores( substring, ignoreFlags );

			TestMethodRecord.Current.RunTest(
				text.EndsWith( substring ),
				"Does end with the substring <" + substring + ">" );

			return this;
		}

		ITestStringsDoes ITestStringsDoes.NotEndWith(string substring)
		{
			return myDoes.NotEndWith( substring, Ignoring.Nothing );
		}

		ITestStringsDoes ITestStringsDoes.NotEndWith(string substring, Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			substring = TransformByIgnores( substring, ignoreFlags );

			TestMethodRecord.Current.RunTest(
				!text.EndsWith( substring ),
				"Does not end with the substring <" + substring + ">" );

			return this;
		}

		void ITestExtension.Go()
		{
			throw new NotImplementedException();
		}

		ITestStringsIs ITestStringsIs.LongerThan(int length)
		{
			TestMethodRecord.Current.RunTest( textUnderTest.Length > length, 
				"String is longer than " + length + "." );

			return this;
		}

		ITestStringsIs ITestStringsIs.NotLongerThan(int length)
		{
			TestMethodRecord.Current.RunTest( textUnderTest.Length <= length,
				"String is not longer than " + length + "." );

			return this;
		}

		ITestStringsIs ITestStringsIs.ShorterThan(int length)
		{
			TestMethodRecord.Current.RunTest( textUnderTest.Length < length,
				"String is shorter than " + length + "." );

			return this;
		}

		ITestStringsIs ITestStringsIs.NotShorterThan(int length)
		{
			TestMethodRecord.Current.RunTest( textUnderTest.Length >= length,
				"String is not shorter than " + length + "." );

			return this;
		}

		ITestStringsIs ITestStringsIs.Equal(string expectedText)
		{
			TestMethodRecord.Current.Are.Equal( expectedText, textUnderTest );
			return this;
		}

		ITestStringsIs ITestStringsIs.NotEqual(string expectedText)
		{
			TestMethodRecord.Current.Are.NotEqual( expectedText, textUnderTest );
			return this;
		}

		ITestStringsIs ITestStringsIs.NullOrEmpty()
		{
			return myIs.NullOrEmpty( Ignoring.Nothing );
		}

		ITestStringsIs ITestStringsIs.NullOrEmpty(Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			TestMethodRecord.Current.Is.NotNullOrEmpty( text );
			return this;
		}

		ITestStringsIs ITestStringsIs.Empty()
		{
			return myIs.Empty( Ignoring.Nothing );
		}

		ITestStringsIs ITestStringsIs.Empty(Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			TestMethodRecord.Current.Is.NotNullOrEmpty( text );
			return this;
		}

		ITestStringsIs ITestStringsIs.NotNullOrEmpty()
		{
			return myIs.NullOrEmpty( Ignoring.Nothing );
		}

		ITestStringsIs ITestStringsIs.NotNullOrEmpty(Ignoring ignoreFlags)
		{



			throw new NotImplementedException();



		}

		ITestStringsIs ITestStringsIs.NotEmpty()
		{
			return myIs.NotEmpty( Ignoring.Nothing );
		}

		ITestStringsIs ITestStringsIs.NotEmpty(Ignoring ignoreFlags)
		{



			throw new NotImplementedException();




		}

		ITestStringsIs ITestStringsIs.Null()
		{
			TestMethodRecord.Current.Is.Null( textUnderTest );
			return this;
		}

		ITestStringsIs ITestStringsIs.NotNull()
		{
			TestMethodRecord.Current.Is.NotNull( textUnderTest );
			return this;
		}

		ITestStringsIs ITestStringAnd.Is()
		{
			return this;
		}

		ITestStringsDoes ITestStringAnd.Does()
		{
			return this;
		}

		public ITestStringsIs Equal(string expectedText, Ignoring ignoreFlags)
		{
			string text = TransformByIgnores( textUnderTest, ignoreFlags );
			expectedText = TransformByIgnores( expectedText, ignoreFlags );

			TestMethodRecord.Current.Are.Equal( expectedText, text );

			return this;
		}

		public ITestStringsIs Uppercase()
		{
			throw new NotImplementedException();
		}

		public ITestStringsIs Lowercase()
		{
			throw new NotImplementedException();
		}

		public ITestStringsIs Number()
		{
			throw new NotImplementedException();
		}

		public ITestStringsIs Letters()
		{
			throw new NotImplementedException();
		}

		public ITestStringsIs LettersAndDigits()
		{
			throw new NotImplementedException();
		}
	}
}
